from datetime import date, datetime  # 🌟 导入 datetime
from random import randint
from models import db, User, DailyRecord, WrongQuestion
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from flask import current_app
import random

# --- 1. 口算生成逻辑 (核心功能) ---

# services.py（修改 _generate_single_quiz 函数）
def _generate_single_quiz(grade):
    """根据年级生成一道口算题"""
    # 难度逻辑 (简化版)：
    if grade == 1:
        # 一年级：10以内加减法
        op = '+' if randint(0, 1) == 0 else '-'
        a = randint(1, 9)
        b = randint(1, 9)
        # 确保减法结果大于等于 0
        if op == '-' and a < b:
            a, b = b, a

        question = f"{a} {op} {b} ="
        correct_answer = str(eval(question[:-1]))  # Python eval() 用于计算结果

        # 模拟选项生成
        options = [correct_answer, str(int(correct_answer) + 1), str(int(correct_answer) - 1),
                   str(int(correct_answer) + 2)]
        options = list(set(options))  # 去重
        # 新增：随机打乱选项顺序
        random.shuffle(options)

        return question, correct_answer, options

    elif grade >= 2:
        # 二年级及以上：模拟乘法
        op = '*'
        a = randint(2, 9)
        b = randint(2, 9)
        question = f"{a} {op} {b} ="
        correct_answer = str(eval(question[:-1]))
        options = [correct_answer, str(int(correct_answer) + 1), str(int(correct_answer) - 1),
                   str(int(correct_answer) + 2)]
        options = list(set(options))  # 去重
        # 新增：随机打乱选项顺序
        random.shuffle(options)
        return question, correct_answer, options

    return "1 + 1 =", "2", ["1", "2", "3", "4"]


def generate_quiz(user_id):
    """为用户生成一套口算题"""
    try:
        user = db.session.get(User, user_id)
        if not user:
            return None, 40003

        questions = []
        for i in range(current_app.config['DAILY_QUIZ_COUNT']):
            content, answer, options = _generate_single_quiz(user.grade)
            questions.append({
                "question_id": i + 1,
                "type": "math",
                "content": content,
                "options": options
                # "answer": answer  # 备注要求：实际项目中不应该返回答案给前端
            })

        # 实际项目中，这里需要将题目内容和正确答案存储在缓存或数据库中，用于后续提交时的校验
        # (由于没有缓存，我们将依赖客户端在 /submit 时传回 'content'，见 calculate_and_save_result)

        return questions, 0
    except Exception as e:
        print(f"题目生成错误: {e}")
        return None, 50002


# --- 2. 答案提交与数据记录逻辑 ---

def calculate_and_save_result(user_id, session_id, answers):
    """计算结果、更新每日记录、记录错题"""

    # 实际项目中，需要根据 session_id 从缓存/数据库中取出题目的正确答案进行校验
    # (🌟 备注实现：由于没有缓存，我们改为依赖 'answers' 负载包含 'content' 字段来进行实时校验)

    # 备注要求：替换 "模拟校验结果"
    if not isinstance(answers, list):
        return None, 40003  # 答案格式错误

    total_count = len(answers)
    correct_count = 0
    
    # 用于存储 (content, correct_answer)
    wrong_questions_to_log = [] 

    for ans in answers:
        content = ans.get('content')
        user_answer = ans.get('user_answer')

        # 必须提供 content 和 user_answer
        if not content or user_answer is None:
            current_app.logger.warning(f"Submit 负载格式错误，缺少 content 或 user_answer: {ans}")
            return None, 40003 

        try:
            # 重新计算正确答案
            # _generate_single_quiz 使用 eval(question[:-1])
            correct_answer = str(eval(content[:-1]))
        except Exception as e:
            current_app.logger.error(f"无法解析 'content' {content}: {e}")
            correct_answer = "N/A" # 标记为无法解析

        if user_answer == correct_answer:
            correct_count += 1
        else:
            # 备注要求：替换 "记录错题 (模拟)"
            wrong_questions_to_log.append({
                "content": content,
                "correct_answer": correct_answer,
                "user_answer": user_answer 
            })

    accuracy_rate = 0.0
    if total_count > 0:
        accuracy_rate = round((correct_count / total_count) * 100, 2)

    is_daily_limit_reached = True

    try:
        # 1. 更新 DailyRecord (或创建)
        today = date.today()
        record = db.session.scalar(db.select(DailyRecord).filter_by(user_id=user_id, date=today))

        if record:
            record.total_completed += total_count
            record.correct_count += correct_count
            # 重新计算累计正确率
            if record.total_completed > 0: # 避免除零
                record.accuracy_rate = round((record.correct_count / record.total_completed) * 100, 2)
            else:
                record.accuracy_rate = 0.0
        else:
            record = DailyRecord(user_id=user_id, date=today, total_completed=total_count, correct_count=correct_count,
                                 accuracy_rate=accuracy_rate)
            db.session.add(record)

        # 2. 记录错题 (替换模拟)
        for wq_data in wrong_questions_to_log:
            wrong_content = wq_data["content"]
            correct_answer = wq_data["correct_answer"]

            # 尝试查找现有错题，更新次数
            wrong_q = db.session.scalar(db.select(WrongQuestion).filter_by(user_id=user_id, content=wrong_content))
            if wrong_q:
                wrong_q.mistake_count += 1
                wrong_q.last_mistake_date = datetime.utcnow()
            else:
                new_wrong_q = WrongQuestion(user_id=user_id, content=wrong_content, correct_answer=correct_answer,
                                            mistake_count=1)
                db.session.add(new_wrong_q)

        db.session.commit()
        return {
            "correct_count": correct_count,
            "total_count": total_count,
            "accuracy_rate": accuracy_rate,
            "is_daily_limit_reached": is_daily_limit_reached
        }, 0

    except IntegrityError as e:
        db.session.rollback()
        current_app.logger.error(f"calculate_and_save_result IntegrityError: {e}")
        return None, 50001
    except SQLAlchemyError as e:
        db.session.rollback()
        current_app.logger.error(f"calculate_and_save_result SQLAlchemyError: {e}")
        return None, 50001
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"calculate_and_save_result 未知错误: {e}")
        return None, 50099


# --- 3. 数据查询逻辑 ---

def get_historical_stats(user_id, start_date_str, end_date_str):
    """获取指定日期范围内的每日记录"""
    try:
        # 备注要求：实际项目中，需要将字符串日期转换为 date 对象
        try:
            start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
            end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
        except ValueError:
            # 40003: 必填参数缺失或格式错误
            return None, 40003 

        # 备注要求：实际：从 DailyRecord 表中查询并转换为字典列表
        records_query = db.session.scalars(
            db.select(DailyRecord)
            .filter_by(user_id=user_id)
            .filter(DailyRecord.date >= start_date, DailyRecord.date <= end_date)
            .order_by(DailyRecord.date.asc())
        ).all()

        records = []
        for rec in records_query:
            records.append({
                "date": rec.date.isoformat(),
                "completed_count": rec.total_completed,
                "correct_count": rec.correct_count,
                "accuracy_rate": rec.accuracy_rate
            })

        return records, 0
    except Exception as e:
        current_app.logger.error(f"get_historical_stats 失败: {e}")
        return None, 50001